package com.pshcp.doctor.api;

import com.external.hospital.ap.UserApManager;
import com.external.service.HisTreatmentRequestService;
import com.external.ws.hisTreatment.dto.TreatmentCanBookDTO;
import com.external.ws.hisTreatment.dto.TreatmentLocationDTO;
import com.external.ws.hisTreatment.dto.TreatmentReserveExecuteDTO;
import com.external.ws.hisTreatment.res.TreatmentCanBook;
import com.external.ws.hisTreatment.res.TreatmentLocation;
import com.external.ws.hisTreatment.res.TreatmentReserveExecute;
import com.framework.base.PageList;
import com.framework.base.ResultBuilder;
import com.framework.base.ResultDTO;
import com.framework.exception.BizException;
import com.framework.logaop.Log;
import com.framework.logaop.LogSourceEnum;
import com.framework.logaop.LogTypeEnum;
import com.framework.thread.ReqComTool;
import com.framework.tool.CommonTool;
import com.framework.util.DateUtil;
import com.pshcp.doctor.ao.common.CommonAO;
import com.pshcp.doctor.ao.patientreserve.ConfirmTreatmentReserveOperateAO;
import com.pshcp.doctor.ao.patientreserve.SaveTreatmentReserveAO;
import com.pshcp.doctor.ao.patientreserve.TreatmentCanBookAO;
import com.pshcp.doctor.ao.patientreserve.TreatmentReservePageAO;
import com.pshcp.doctor.tool.DoctorWorkCalendarTool;
import com.pshcp.doctor.tool.PatientReserveTool;
import com.pshcp.doctor.vo.patientreserve.PatientReserveRecordListVO;
import com.pshcp.doctor.vo.patientreserve.PatientReserveRecordVO;
import com.pshcp.doctor.vo.patientreserve.PatientReserveTypeVO;
import com.pshcp.doctor.vo.patientreserve.TreatmentCanBookVO;
import com.pshcp.doctor.vo.patientreserve.TreatmentLocationVO;
import com.pshcp.domain.dto.PatientReserveRecordDTO;
import com.pshcp.domain.dto.SysDictYyDTO;
import com.pshcp.domain.model.*;
import com.pshcp.manager.messagenotification.MessageNotificationDTO;
import com.pshcp.manager.messagenotification.MessageNotificationManager;
import com.pshcp.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * @Description: TODO
 * @Author: xiaoche
 * @Date: 2022/11/18 19:43
 */
@Api(tags = {"医生端-患者预约操作接口"})
@Slf4j
@RestController
@RequestMapping("/api/doctor/patientReserve")
public class PatientReserveAPI {

    @Autowired
    private PatientReserveRecordService patientReserveRecordService;

    @Autowired
    private PatientReserveOperateRecordService patientReserveOperateRecordService;

    @Autowired
    private PatientReserveCodeService patientReserveCodeService;

    @Autowired
    private HisTreatmentRequestService hisTreatmentRequestService;

    @Autowired
    private DoctorService doctorService;

    @Autowired
    private PatientService patientService;
    @Autowired
    private DoctorWorkCalendarMemoService doctorWorkCalendarMemoService;
    @Autowired
    private SysDictYyService sysDictYyService;
    @Autowired
    private MessageNotificationManager messageNotificationManager;
    @Autowired
    private UserApManager userApManager;

    @ApiOperation("获取治疗项目")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取治疗项目")
    @PostMapping("getTreatmentList")
    public ResultDTO<List<PatientReserveTypeVO>> getTreatmentList() {
        List<PatientReserveCode> patientReserveCodes = patientReserveCodeService.getPatientReserveCodeList();
        List<PatientReserveTypeVO> list = CommonTool.copyPropertiesList(patientReserveCodes, PatientReserveTypeVO.class);
        return ResultBuilder.success(list);
    }

    @ApiOperation("获取治疗地点")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取治疗地点")
    @PostMapping("geTreatmentLocationList")
    public ResultDTO<List<TreatmentLocationVO>> geTreatmentLocationList() throws BizException {
        TreatmentLocationDTO dto = new TreatmentLocationDTO();
        dto.setHosDistId(0);
        List<TreatmentLocation> treatmentLocationList = hisTreatmentRequestService.treatmentLocationList(dto);
        List<TreatmentLocationVO> list = CommonTool.copyPropertiesList(treatmentLocationList, TreatmentLocationVO.class);
        return ResultBuilder.success(list);
    }

    @ApiOperation("获取预约治疗时间段")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取预约治疗时间段")
    @PostMapping("getTreatmentBookTimeList")
    public ResultDTO<List<TreatmentCanBookVO>> getTreatmentBookTimeList(@RequestBody TreatmentCanBookAO treatmentCanBookAO) throws BizException {
        PatientReserveTool.checkGetTreatmentBookTimeList(treatmentCanBookAO);
        PatientReserveCode patientReserveCode = patientReserveCodeService.getPatientReserveCodeByType(treatmentCanBookAO.getType());
        if (patientReserveCode == null || StringUtils.isBlank(patientReserveCode.getItemCode())) {
            return ResultBuilder.failure("10190005");
        }
        TreatmentCanBookDTO dto = PatientReserveTool.buildTreatmentCanBookDTO(treatmentCanBookAO, patientReserveCode.getItemCode());
        List<TreatmentCanBook> treatmentCanBookList = hisTreatmentRequestService.treatmentCanBook(dto);
        List<TreatmentCanBookVO> list = CommonTool.copyPropertiesList(treatmentCanBookList, TreatmentCanBookVO.class);
        return ResultBuilder.success(list);
    }

    @ApiOperation("获取手术治疗诊断")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取手术治疗诊断")
    @PostMapping("getDiagnoseList")
    public ResultDTO<List<SysDictYyDTO>> getDiagnoseList() throws BizException {
        SysDictYy sysDictDTO = new SysDictYy();
        sysDictDTO.setDictType(SysDictYy.DICT_TYPE_DIAGNOSE);
        List<SysDictYyDTO> list = sysDictYyService.querySysDictList(sysDictDTO);
        return ResultBuilder.success(list);
    }

    @ApiOperation("获取手术治疗手术名称")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取手术治疗手术名称")
    @PostMapping("getOperationNameList")
    public ResultDTO<List<SysDictYyDTO>> getOperationNameList(@RequestBody SysDictYy sysDictYy) throws BizException {
        SysDictYy sysDictDTO = new SysDictYy();
        sysDictDTO.setDictType(SysDictYy.DICT_TYPE_OPERATION_NAME);
        sysDictDTO.setDictCode(sysDictYy.getDictCode());
        List<SysDictYyDTO> list = sysDictYyService.querySysDictList(sysDictDTO);
        return ResultBuilder.success(list);
    }

    @ApiOperation("获取手术治疗手术地址")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取手术治疗手术名称")
    @PostMapping("getOperationAddressList")
    public ResultDTO<List<SysDictYyDTO>> getOperationAddressList() throws BizException {
        SysDictYy sysDictDTO = new SysDictYy();
        sysDictDTO.setDictType(SysDictYy.DICT_TYPE_OPERATION_ADDRESS);
        List<SysDictYyDTO> list = sysDictYyService.querySysDictList(sysDictDTO);
        return ResultBuilder.success(list);
    }

    @ApiOperation("获取手术治疗手术时间")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取手术治疗手术名称")
    @PostMapping("getOperationTimeList")
    public ResultDTO<List<TreatmentCanBookVO>> getOperationTimeList(@RequestBody TreatmentCanBookAO treatmentCanBookAO) throws BizException {
        List<TreatmentCanBookVO> list = new ArrayList<>();
        TreatmentCanBookVO treatmentCanBookVO1 = new TreatmentCanBookVO();
        treatmentCanBookVO1.setStartTime("8:00");
        treatmentCanBookVO1.setEndTime("8:30");
        treatmentCanBookVO1.setBookedNum(1);
        treatmentCanBookVO1.setCanBookNum(14);
        list.add(treatmentCanBookVO1);

        TreatmentCanBookVO treatmentCanBookVO2 = new TreatmentCanBookVO();
        treatmentCanBookVO2.setStartTime("8:30");
        treatmentCanBookVO2.setEndTime("9:00");
        treatmentCanBookVO2.setBookedNum(2);
        treatmentCanBookVO2.setCanBookNum(13);
        list.add(treatmentCanBookVO2);

        TreatmentCanBookVO treatmentCanBookVO3 = new TreatmentCanBookVO();
        treatmentCanBookVO3.setStartTime("9:00");
        treatmentCanBookVO3.setEndTime("9:30");
        treatmentCanBookVO3.setBookedNum(0);
        treatmentCanBookVO3.setCanBookNum(15);
        list.add(treatmentCanBookVO3);

        TreatmentCanBookVO treatmentCanBookVO4 = new TreatmentCanBookVO();
        treatmentCanBookVO4.setStartTime("9:30");
        treatmentCanBookVO4.setEndTime("10:00");
        treatmentCanBookVO4.setBookedNum(0);
        treatmentCanBookVO4.setCanBookNum(15);
        list.add(treatmentCanBookVO4);
        return ResultBuilder.success(list);
    }

    @ApiOperation("保存预约治疗")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "保存预约治疗")
    @PostMapping("saveTreatmentReserve")
    public ResultDTO<Long> saveTreatmentReserve(@RequestBody SaveTreatmentReserveAO saveTreatmentReserveAO) throws BizException {
        PatientReserveCode patientReserveCode = new PatientReserveCode();
        if(saveTreatmentReserveAO.getHandleType() == 0){    // 治疗预约
            patientReserveCode = patientReserveCodeService.getPatientReserveCodeByType(saveTreatmentReserveAO.getType());
            /*if (patientReserveCode == null || StringUtils.isBlank(patientReserveCode.getItemCode())) {
                return ResultBuilder.failure("10190006");
            }*/
        }
        Long userId = ReqComTool.getUserId();
        Doctor doctor = doctorService.findById(userId);
        Patient patient = patientService.getPatientByCardNo(saveTreatmentReserveAO.getPatCardType(), saveTreatmentReserveAO.getPatCardNo());
        PatientReserveRecord patientReserveRecord = PatientReserveTool.buildSaveTreatmentReserve(doctor, patient, patientReserveCode, saveTreatmentReserveAO);
        patientReserveRecordService.insert(patientReserveRecord);

        List<PatientReserveOperateRecord> patientReserveOperateRecordList = PatientReserveTool.buildPatientReserveOperateRecordList(patientReserveRecord);
        patientReserveOperateRecordService.batchSavePatientReserveOperateRecord(patientReserveOperateRecordList);

        if (patientReserveRecord.getBizStatus() == 1) {
            TreatmentReserveExecuteDTO treatmentReserveExecuteDTO = PatientReserveTool.buildSaveTreatmentReserveExecuteDTO(patientReserveRecord);
            TreatmentReserveExecute treatmentReserveExecute = hisTreatmentRequestService.treatmentReserveExecute(treatmentReserveExecuteDTO);
            patientReserveRecord.setAccessReserveStatus(1);
            patientReserveRecord.setAccessReserveNo(treatmentReserveExecute.getAccessReserveNo());
            patientReserveRecord.setAccessReserveInitTime(DateUtil.currDate());
            patientReserveRecordService.update(patientReserveRecord);
        }
        // 预约成功，添加日历
        DoctorWorkCalendarMemo saveDoctorWorkCalendarMemo = DoctorWorkCalendarTool.buildSaveDoctorWorkCalendarMemo(saveTreatmentReserveAO, ReqComTool.getUserId());
        doctorWorkCalendarMemoService.insert(saveDoctorWorkCalendarMemo);
        // 预约成功，添加科密日历
        DoctorWorkCalendarMemo saveDoctorWorkCalendarMemoKm = DoctorWorkCalendarTool.buildSaveDoctorWorkCalendarMemo(saveTreatmentReserveAO, 808925905966596097L);
        doctorWorkCalendarMemoService.insert(saveDoctorWorkCalendarMemoKm);
        return ResultBuilder.success(patientReserveRecord.getId());
    }

    @ApiOperation("获取预约治疗列表（分页）")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.SELECT, desc = "获取预约治疗列表（分页）")
    @PostMapping("getTreatmentReservePage")
    public ResultDTO<PageList<PatientReserveRecordListVO>> getTreatmentReservePage(@RequestBody TreatmentReservePageAO treatmentReservePageAO) throws BizException {
        Doctor doctor = null;
        if (ReqComTool.getUserType() == 0) {
            doctor = doctorService.findById(ReqComTool.getUserId());
        }
        PatientReserveRecordDTO patientReserveRecordDTO = PatientReserveTool.buildGetTreatmentReservePage(doctor, treatmentReservePageAO);
        PageList<PatientReserveRecord> pageList = patientReserveRecordService.list(patientReserveRecordDTO);
        PageList<PatientReserveRecordListVO> page = CommonTool.buildPageList(pageList, PatientReserveRecordListVO.class);
        return ResultBuilder.success(page);
    }

    @ApiOperation("获取预约治疗")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "获取预约治疗")
    @PostMapping("getTreatmentReserveById")
    public ResultDTO<PatientReserveRecordVO> getTreatmentReserveById(@RequestBody CommonAO commonAO) throws BizException {
        CommonTool.checkObj(commonAO.getId(), "90000006");
        PatientReserveRecord patientReserveRecord = patientReserveRecordService.findById(commonAO.getId());
        CommonTool.checkObj(patientReserveRecord, "90000007");
        Map<Long, List<PatientReserveOperateRecord>> patientReserveOperateRecordMap = patientReserveOperateRecordService.getPatientReserveOperateRecordByReserveRecordIds(Collections.singletonList(patientReserveRecord.getId()));
        PatientReserveRecordVO patientReserveRecordVO = PatientReserveTool.buildPatientReserveRecordVO(doctorService, patientReserveRecord, patientReserveOperateRecordMap);
        if(ReqComTool.getUserType() == 0){      // 医生登录
            Doctor doctor = doctorService.findById(ReqComTool.getUserId());
            patientReserveRecordVO.setSecretaryFlag(doctor.getSecretaryFlag());
        }
        return ResultBuilder.success(patientReserveRecordVO);
    }

    @ApiOperation("取消预约治疗")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "取消预约治疗")
    @PostMapping("cancelTreatmentReserve")
    public ResultDTO<Long> cancelTreatmentReserve(@RequestBody CommonAO commonAO) throws BizException {
        CommonTool.checkObj(commonAO.getId(), "90000006");
        PatientReserveRecord patientReserveRecord = patientReserveRecordService.findById(commonAO.getId());
        CommonTool.checkObj(patientReserveRecord, "90000007");
        if (!patientReserveRecord.getDoctorId().equals(ReqComTool.getUserId())) {
            return ResultBuilder.failure("90000013");
        }
        if (patientReserveRecord.getAccessReserveStatus() != 0) {
            return ResultBuilder.failure("90000011");
        }
        patientReserveRecord.setBizStatus(4);
        patientReserveRecordService.update(patientReserveRecord);
        try{
            TreatmentReserveExecuteDTO treatmentReserveExecuteDTO = PatientReserveTool.buildCancelTreatmentReserveExecuteDTO(patientReserveRecord);
            hisTreatmentRequestService.treatmentReserveExecute(treatmentReserveExecuteDTO);
        }catch (Exception e){
            log.error("取消预约同步his数据失败");
        }
        patientReserveRecord.setAccessReserveStatus(2);
        patientReserveRecord.setAccessReserveCancelTime(DateUtil.currDate());
        patientReserveRecordService.update(patientReserveRecord);
        return ResultBuilder.success(patientReserveRecord.getId());
    }

    @ApiOperation("确认预约治疗操作")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "确认预约治疗操作")
    @PostMapping("confirmTreatmentReserveOperate")
    public ResultDTO<Long> confirmTreatmentReserveOperate(@RequestBody ConfirmTreatmentReserveOperateAO confirmTreatmentReserveOperateAO) throws BizException {
        CommonTool.checkObj(confirmTreatmentReserveOperateAO.getPatientReserveRecordId(), "90000006");
        PatientReserveRecord patientReserveRecord = patientReserveRecordService.findById(confirmTreatmentReserveOperateAO.getPatientReserveRecordId());
        CommonTool.checkObj(patientReserveRecord, "90000007");
        ResultDTO resultDTO = patientReserveOperateRecordService.confirmTreatmentReserveOperate(confirmTreatmentReserveOperateAO.getPatientReserveRecordId(), patientReserveRecord);
        // 返回成功修改申请
        if(resultDTO.getSuccess()){
            Integer bizStatus = ReqComTool.getUserType() == 0 ? 1 : 5;
            patientReserveRecord.setBizStatus(bizStatus);
            patientReserveRecordService.update(patientReserveRecord);
            try{
                TreatmentReserveExecuteDTO treatmentReserveExecuteDTO = PatientReserveTool.buildSaveTreatmentReserveExecuteDTO(patientReserveRecord);
                TreatmentReserveExecute treatmentReserveExecute = hisTreatmentRequestService.treatmentReserveExecute(treatmentReserveExecuteDTO);
                patientReserveRecord.setAccessReserveNo(treatmentReserveExecute.getAccessReserveNo());
            }catch (Exception e){
                log.error("确认预约同步his数据失败");
            }
            patientReserveRecord.setAccessReserveStatus(1);
            patientReserveRecord.setAccessReserveInitTime(DateUtil.currDate());
            patientReserveRecordService.update(patientReserveRecord);
            if(ReqComTool.getUserType() == 0) {      // 医生登录
                // 查询最后一次登录用户id
                Long patientUserId = patientService.queryPatient(patientReserveRecord.getPatCardNo());
                // 推送系统消息给患者
                MessageNotificationDTO messageNotificationDTO = buildPatientReserveIM2MessageNotificationDTO(patientUserId, patientReserveRecord);
                messageNotificationManager.sendMessageNotification(messageNotificationDTO);
                // 推送IM系统消息
                userApManager.sendSystemMessage(patientReserveRecord.getDoctorId(), patientUserId, "4");
                userApManager.sendSystemMessage(patientReserveRecord.getDoctorId(), patientReserveRecord.getPatientId(), "4");
            }
        }
        return resultDTO;
    }

    @ApiOperation("确认预约治疗操作")
    @Log(source = LogSourceEnum.APP, type = LogTypeEnum.UPDATE, desc = "确认预约治疗操作")
    @PostMapping("confirmTreatmentReserveOperateOld")
    public ResultDTO<Long> confirmTreatmentReserveOperateOld(@RequestBody ConfirmTreatmentReserveOperateAO confirmTreatmentReserveOperateAO) throws BizException {
        CommonTool.checkObj(confirmTreatmentReserveOperateAO.getPatientReserveRecordId(), "90000006");
        CommonTool.checkObj(confirmTreatmentReserveOperateAO.getPatientReserveOperateRecordId(), "90000006");
        PatientReserveRecord patientReserveRecord = patientReserveRecordService.findById(confirmTreatmentReserveOperateAO.getPatientReserveRecordId());
        CommonTool.checkObj(patientReserveRecord, "90000007");
        if (patientReserveRecord.getAccessReserveStatus() != 0) {
            return ResultBuilder.failure("90000011");
        }
        Doctor doctor = null;
        if (ReqComTool.getUserType() == 0) {
            doctor = doctorService.findById(ReqComTool.getUserId());
        }
        List<PatientReserveOperateRecord> beforeReserveOperateRecords = patientReserveOperateRecordService.getPatientReserveOperateRecordByReserveRecordId(patientReserveRecord.getId());
        PatientReserveOperateRecord patientReserveOperateRecord = PatientReserveTool.dealPatientReserveOperateRecord(doctor, beforeReserveOperateRecords, confirmTreatmentReserveOperateAO);
        patientReserveOperateRecord.setBizStatus(1);
        patientReserveOperateRecordService.update(patientReserveOperateRecord);

        List<PatientReserveOperateRecord> reserveOperateRecords = patientReserveOperateRecordService.getPatientReserveOperateRecordByReserveRecordId(patientReserveRecord.getId());
        boolean patientReserveBizStatus = PatientReserveTool.checkPatientReserveBizStatus(reserveOperateRecords);
        if (patientReserveBizStatus) {
            patientReserveRecord.setBizStatus(1);
            patientReserveRecordService.update(patientReserveRecord);
            TreatmentReserveExecuteDTO treatmentReserveExecuteDTO = PatientReserveTool.buildSaveTreatmentReserveExecuteDTO(patientReserveRecord);
            TreatmentReserveExecute treatmentReserveExecute = hisTreatmentRequestService.treatmentReserveExecute(treatmentReserveExecuteDTO);
            patientReserveRecord.setAccessReserveStatus(1);
            patientReserveRecord.setAccessReserveNo(treatmentReserveExecute.getAccessReserveNo());
            patientReserveRecord.setAccessReserveInitTime(DateUtil.currDate());
            patientReserveRecordService.update(patientReserveRecord);
        }
        return ResultBuilder.success(null);
    }

    // 预约系统消息
    public MessageNotificationDTO buildPatientReserveIM2MessageNotificationDTO(Long userId, PatientReserveRecord patientReserveRecord) {
        MessageNotificationDTO messageNotificationDTO = new MessageNotificationDTO();
        messageNotificationDTO.setTitle(patientReserveRecord.getHandleType() == 0 ? "治疗预约确认" : "手术预约确认");
        messageNotificationDTO.setDescription(null);
        messageNotificationDTO.setMessageType(patientReserveRecord.getHandleType() == 0 ? 11 : 12);
        messageNotificationDTO.setUserType(1);
        messageNotificationDTO.setUserId(userId);
        messageNotificationDTO.setDataId(patientReserveRecord.getId());
        return messageNotificationDTO;
    }
}
